package com.icesoft.system.safe.filter.impl;

import com.icesoft.framework.core.cache.RedisCacheManager;
import com.icesoft.framework.core.util.ResponseUtils;
import com.icesoft.framework.core.vo.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class TimeUnitNonceStrFilter {

	private static final long timeUnitExpired = 5; //分钟

	private static final String NONCE_STR_NAME = "nonceStr";
	private static final String TIME_UNIT_NAME = "timeUnit";

	@Resource
	private RedisCacheManager redisService;

	public static String getNonceStr(HttpServletRequest request) {
		String nonceStr = request.getParameter(NONCE_STR_NAME);
		if (nonceStr == null) {
			nonceStr = request.getHeader(NONCE_STR_NAME);
		}
		return nonceStr;
	}

	public static String getTimeUnit(HttpServletRequest request) {
		String timeUnit = request.getParameter(TIME_UNIT_NAME);
		if (timeUnit == null) {
			timeUnit = request.getHeader(TIME_UNIT_NAME);
		}
		return timeUnit;
	}

	public boolean filter(HttpServletRequest request, HttpServletResponse response) {
		String nonceStr = getNonceStr(request);
		String timeUnit = getTimeUnit(request);
		if (StringUtils.isBlank(nonceStr) || StringUtils.isBlank(timeUnit)) {
			ResponseUtils.writeJson(response, JsonResult.FAIL_EXCEPTION("nonceStr和timeUnit不能为空"));
			return false;
		}
		if (nonceStr.length() > 128) {
			ResponseUtils.writeJson(response, JsonResult.FAIL_AUTHENTICATION("nonceStr长度不能超过128位"));
			return false;
		}
		if (redisService.getCacheObject(nonceStr) != null) {
			ResponseUtils.writeJson(response, JsonResult.FAIL_AUTHENTICATION("重复的nonceStr"));
			return false;
		}
		redisService.setCacheObject(nonceStr, true, timeUnitExpired, TimeUnit.MINUTES);

		if (!NumberUtils.isDigits(timeUnit)) {
			log.error("timeUnit错误：" + timeUnit);
			ResponseUtils.writeJson(response, JsonResult.FAIL_AUTHENTICATION("timeUnit错误"));
			return false;
		}
		long timestamp = Long.parseLong(timeUnit);
		int length = timeUnit.length();
		if (length != 13 && length != 10) {
			log.error("timeUnit长度错误：" + timeUnit);
			ResponseUtils.writeJson(response, JsonResult.FAIL_AUTHENTICATION("timeUnit长度错误"));
			return false;
		}

		if (Math.abs(System.currentTimeMillis() - timestamp) > (timeUnitExpired * 60 * 1000)) {
			String msg = "时间错误，请求已失效";
			Instant instant = Instant.ofEpochMilli(timestamp);
			ZoneId zone = ZoneId.systemDefault();
			LocalDateTime userTime = LocalDateTime.ofInstant(instant, zone);
			log.error("timeUnit已失效：{}，{}", timeUnit, userTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
			ResponseUtils.writeJson(response, JsonResult.FAIL_AUTHENTICATION(msg));
			return false;
		}
		return true;
	}

}
